//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Web;
using System.Xml;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Data;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Users;
using DotNetNuke.Security.Permissions;
using DotNetNuke.Security.Roles;
using DotNetNuke.Services.Localization;
using DotNetNuke.Entities.Content;
using DotNetNuke.Entities.Content.Taxonomy;
using DotNetNuke.Services.Exceptions;

namespace DotNetNuke.Entities.Tabs
{
    public class TabController
    {
        private static DataProvider provider = DataProvider.Instance();
        public static TabInfo CurrentPage
        {
            get
            {
                TabInfo _tab = null;
                if (PortalController.GetCurrentPortalSettings() != null)
                {
                    _tab = PortalController.GetCurrentPortalSettings().ActiveTab;
                }
                return _tab;
            }
        }
        private void AddAllTabsModules(TabInfo objTab)
        {
            ModuleController objmodules = new ModuleController();
            foreach (ModuleInfo allTabsModule in objmodules.GetAllTabsModules(objTab.PortalID, true))
            {
                bool canAdd = false;
                foreach (ModuleInfo allTabsInstance in objmodules.GetModuleTabs(allTabsModule.ModuleID))
                {
                    TabInfo tab = new TabController().GetTab(allTabsInstance.TabID, objTab.PortalID, false);
                    if (!tab.IsDeleted)
                    {
                        canAdd = true;
                        break;
                    }
                }
                if (canAdd)
                {
                    objmodules.CopyModule(allTabsModule, objTab, Null.NullString, true);
                }
            }
        }
        private int AddTabInternal(TabInfo objTab, bool includeAllTabsModules)
        {
            bool newTab = true;
            objTab.TabPath = DotNetNuke.Common.Globals.GenerateTabPath(objTab.ParentId, objTab.TabName);
            int iTabID = GetTabByTabPath(objTab.PortalID, objTab.TabPath, objTab.CultureCode);
            if (iTabID > Null.NullInteger)
            {
                throw new TabExistsException(iTabID, "Tab Exists");
            }
            else
            {
                //First create ContentItem as we need the ContentItemID
                IContentTypeController typeController = new ContentTypeController();
                ContentType contentType = (from t in typeController.GetContentTypes()
                                           where t.Type == "Tab"
                                           select t)
                                                 .SingleOrDefault();

                IContentController contentController = DotNetNuke.Entities.Content.Common.Util.GetContentController();
                if (String.IsNullOrEmpty(objTab.Title))
                {
                    objTab.Content = objTab.TabName;
                }
                else
                {
                    objTab.Content = objTab.Title;
                }
                objTab.ContentTypeId = contentType.ContentTypeId;
                objTab.Indexed = false;
                int contentItemID = contentController.AddContentItem(objTab);

                //Add Module
                iTabID = provider.AddTab(contentItemID, objTab.PortalID, objTab.UniqueId, objTab.VersionGuid,
                                         objTab.DefaultLanguageGuid, objTab.LocalizedVersionGuid,
                                         objTab.TabName, objTab.IsVisible, objTab.DisableLink, objTab.ParentId,
                                         objTab.IconFile, objTab.IconFileLarge, objTab.Title, objTab.Description, objTab.KeyWords,
                                         objTab.Url,
                                         objTab.SkinSrc, objTab.ContainerSrc, objTab.TabPath, objTab.StartDate, objTab.EndDate,
                                         objTab.RefreshInterval, objTab.PageHeadText, objTab.IsSecure, objTab.PermanentRedirect,
                                         objTab.SiteMapPriority, UserController.GetCurrentUserInfo().UserID, objTab.CultureCode);
                objTab.TabID = iTabID;
                //Now we have the TabID - update the contentItem
                contentController.UpdateContentItem(objTab);

                ITermController termController = DotNetNuke.Entities.Content.Common.Util.GetTermController();
                termController.RemoveTermsFromContent(objTab);
                foreach (Term _Term in objTab.Terms)
                {
                    termController.AddTermToContent(_Term, objTab);
                }
                Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
                objEventLog.AddLog(objTab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", Services.Log.EventLog.EventLogController.EventLogType.TAB_CREATED);
                TabPermissionController.SaveTabPermissions(objTab);
                try
                {
                    UpdateTabSettings(ref objTab);
                }
                catch (Exception ex)
                {
                    DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
                }
                if (includeAllTabsModules)
                {
                    AddAllTabsModules(objTab);
                }
            }
            return objTab.TabID;
        }
        private void AddTabToEndOfList(TabInfo objTab, bool updateTabPath)
        {
            List<TabInfo> siblingTabs = GetSiblingTabs(objTab);
            TabInfo parentTab = GetTab(objTab.ParentId, objTab.PortalID, false);
            if (parentTab == null)
            {
                objTab.Level = 0;
            }
            else
            {
                objTab.Level = parentTab.Level + 1;
            }
            UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
            objTab.TabOrder = 2 * siblingTabs.Count + 1;
            UpdateTabOrder(objTab, updateTabPath);
        }

        private void DeleteTabInternal(int tabId, int portalId)
        {
            //Get the tab from the Cache
            TabInfo objTab = GetTab(tabId, portalId, false);

            //Delete ant tabModule Instances
            ModuleController moduleCtrl = new ModuleController();
            foreach (ModuleInfo m in moduleCtrl.GetTabModules(tabId).Values)
            {
                moduleCtrl.DeleteTabModule(m.TabID, m.ModuleID, false);
            }

            //Delete Tab
            provider.DeleteTab(tabId);

            //Remove the Content Item
            if (objTab.ContentItemId > Null.NullInteger)
            {
                IContentController ctl = DotNetNuke.Entities.Content.Common.Util.GetContentController();
                ctl.DeleteContentItem(objTab);
            }

            //Log deletion
            Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
            objEventLog.AddLog("TabID", tabId.ToString(), PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, ((int)Services.Log.EventLog.EventLogController.EventLogType.TAB_DELETED).ToString());
        }

        private void DemoteTab(TabInfo objTab, List<TabInfo> siblingTabs)
        {
            int siblingCount = siblingTabs.Count;
            int tabIndex = GetIndexOfTab(objTab, siblingTabs);
            if (tabIndex > 0)
            {
                UpdateTabOrder(siblingTabs, tabIndex + 1, siblingCount - 1, -2);
                TabInfo parentTab = siblingTabs[tabIndex - 1];
                List<TabInfo> descendantTabs = GetTabsByPortal(objTab.PortalID).DescendentsOf(objTab.TabID);
                objTab.ParentId = parentTab.TabID;
                AddTabToEndOfList(objTab, true);
                UpdateDescendantLevel(descendantTabs, 1);
            }
        }
        /*private TabInfo GetTabByNameAndParent(string TabName, int PortalId, int ParentId)
        {
            ArrayList arrTabs = GetTabsByNameAndPortal(TabName, PortalId);
            int intTab = -1;
            if (arrTabs != null)
            {
                switch (arrTabs.Count)
                {
                    case 0:
                        break;
                    case 1:
                        intTab = 0;
                        break;
                    default:
                        int intIndex;
                        TabInfo objTab;
                        for (intIndex = 0; intIndex <= arrTabs.Count - 1; intIndex++)
                        {
                            objTab = (TabInfo)arrTabs[intIndex];
                            if (objTab.ParentId == ParentId)
                            {
                                intTab = intIndex;
                            }
                        }

                        if (intTab == -1)
                        {
                            intTab = 0;
                        }
                        break;
                }
            }
            if (intTab != -1)
            {
                return (TabInfo)arrTabs[intTab];
            }
            else
            {
                return null;
            }
        }
        private ArrayList GetTabsByNameAndPortal(string TabName, int PortalId)
        {
            ArrayList returnTabs = new ArrayList();
            foreach (KeyValuePair<int, TabInfo> kvp in GetTabsByPortal(PortalId))
            {
                TabInfo objTab = kvp.Value;
                if (String.Compare(objTab.TabName, TabName, true) == 0)
                {
                    returnTabs.Add(objTab);
                }
            }
            return returnTabs;
        }
         */

        private int GetIndexOfTab(TabInfo objTab, List<TabInfo> tabs)
        {
            int tabIndex = Null.NullInteger;
            for (int index = 0; index <= tabs.Count - 1; index++)
            {
                if (tabs[index].TabID == objTab.TabID)
                {
                    tabIndex = index;
                    break;
                }
            }
            return tabIndex;
        }

        private List<TabInfo> GetSiblingTabs(TabInfo objTab)
        {
            return GetTabsByPortal(objTab.PortalID).WithCulture(objTab.CultureCode, true).WithParentId(objTab.ParentId);
        }

        private void PromoteTab(TabInfo objTab, List<TabInfo> siblingTabs)
        {
            int siblingCount = siblingTabs.Count;
            TabInfo parentTab = GetTab(objTab.ParentId, objTab.PortalID, false);
            if (parentTab != null)
            {
                int tabIndex = GetIndexOfTab(objTab, siblingTabs);
                UpdateTabOrder(siblingTabs, tabIndex + 1, siblingCount - 1, -2);
                siblingTabs = GetSiblingTabs(parentTab);
                siblingCount = siblingTabs.Count;
                UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
                int parentIndex = GetIndexOfTab(parentTab, siblingTabs);
                UpdateTabOrder(siblingTabs, parentIndex + 1, siblingCount - 1, 2);
                List<TabInfo> descendantTabs = GetTabsByPortal(objTab.PortalID).DescendentsOf(objTab.TabID);
                objTab.ParentId = parentTab.ParentId;
                objTab.TabOrder = parentTab.TabOrder + 2;
                UpdateTab(objTab);
                if (objTab.Level < 0)
                    objTab.Level = 0;
                UpdateTabOrder(objTab, true);
                UpdateDescendantLevel(descendantTabs, -1);
            }
        }
        private void RemoveTab(TabInfo objTab)
        {
            List<TabInfo> siblingTabs = GetSiblingTabs(objTab).Where(t => t.TabID < objTab.TabID).ToList();

            UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
        }
        private void SwapAdjacentTabs(TabInfo firstTab, TabInfo secondTab)
        {
            firstTab.TabOrder -= 2;
            UpdateTabOrder(firstTab, false);
            secondTab.TabOrder += 2;
            UpdateTabOrder(secondTab, false);
        }
        private void UpdateChildTabPath(int intTabid, int portalId)
        {
            foreach (TabInfo childTab in GetTabsByPortal(portalId).DescendentsOf(intTabid))
            {
                string oldTabPath = childTab.TabPath;
                childTab.TabPath = DotNetNuke.Common.Globals.GenerateTabPath(childTab.ParentId, childTab.TabName);
                if (oldTabPath != childTab.TabPath)
                {
                    if(childTab.ContentItemId == Null.NullInteger && childTab.TabID != Null.NullInteger)
                    {
                        CreateContentItem(childTab);
                    }

                    provider.UpdateTab(childTab.TabID, childTab.ContentItemId, childTab.PortalID, childTab.VersionGuid,
                                       childTab.DefaultLanguageGuid, childTab.LocalizedVersionGuid,
                                       childTab.TabName, childTab.IsVisible, childTab.DisableLink,
                                       childTab.ParentId, childTab.IconFile, childTab.IconFileLarge, childTab.Title, childTab.Description,
                                       childTab.KeyWords, childTab.IsDeleted, childTab.Url, childTab.SkinSrc, childTab.ContainerSrc,
                                       childTab.TabPath, childTab.StartDate, childTab.EndDate, childTab.RefreshInterval,
                                       childTab.PageHeadText, childTab.IsSecure, childTab.PermanentRedirect,
                                       childTab.SiteMapPriority, UserController.GetCurrentUserInfo().UserID, childTab.CultureCode);
                    UpdateTabVersion(childTab.TabID);
                    Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
                    objEventLog.AddLog("TabID", intTabid.ToString(), PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, Services.Log.EventLog.EventLogController.EventLogType.TAB_UPDATED);
                }
            }
        }
        private void UpdateDescendantLevel(List<TabInfo> descendantTabs, int levelDelta)
        {
            foreach (TabInfo descendent in descendantTabs)
            {
                descendent.Level = descendent.Level + levelDelta;
                UpdateTabOrder(descendent, true);
            }
        }

        private void UpdateTabOrder(TabInfo objTab, bool updateTabPath)
        {
            if (updateTabPath)
            {
                objTab.TabPath = DotNetNuke.Common.Globals.GenerateTabPath(objTab.ParentId, objTab.TabName);
            }
            provider.UpdateTabOrder(objTab.TabID, objTab.TabOrder, objTab.Level, objTab.ParentId, objTab.TabPath, UserController.GetCurrentUserInfo().UserID);
            UpdateTabVersion(objTab.TabID);
            Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
            objEventLog.AddLog(objTab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID,
                               "", Services.Log.EventLog.EventLogController.EventLogType.TAB_ORDER_UPDATED);
            ClearCache(objTab.PortalID);
        }
        private void UpdateTabOrder(List<TabInfo> tabs, int startIndex, int endIndex, int increment)
        {
            for (int index = startIndex; index <= endIndex; index++)
            {
                TabInfo objTab = tabs[index];
                objTab.TabOrder += increment;
                UpdateTabOrder(objTab, false);
            }
        }


        private void UpdateTabOrder(List<TabInfo> tabs, string culture, int portalId, int increment)
        {
            PortalSettings _PortalSettings = PortalController.GetCurrentPortalSettings();
            if (_PortalSettings != null && _PortalSettings.ContentLocalizationEnabled)
            {
                if (string.IsNullOrEmpty(culture))
                {
                    UpdateTabOrderInternal(tabs.Where(t => t.CultureCode == _PortalSettings.DefaultLanguage || string.IsNullOrEmpty(t.CultureCode)), increment);
                }
                else
                {
                    UpdateTabOrderInternal(tabs, increment);
                }
            }
            else
            {
                UpdateTabOrderInternal(tabs, increment);
            }
        }


        private void UpdateTabOrderInternal(IEnumerable<TabInfo> tabs, int increment)
        {
            int tabOrder = 1;
            foreach (TabInfo objTab in tabs.OrderBy(t => t.TabOrder))
            {
                if (objTab.IsDeleted)
                {
                    objTab.TabOrder = -1;
                    UpdateTabOrder(objTab, false);

                    //Update the tab order of all child languages
                    foreach (TabInfo localizedtab in objTab.LocalizedTabs.Values)
                    {
                        localizedtab.TabOrder = -1;
                        UpdateTabOrder(localizedtab, false);
                    }
                }
                else
                {
                    //Only update the tabOrder if it actually needs to be updated
                    if ((objTab.TabOrder != tabOrder))
                    {
                        objTab.TabOrder = tabOrder;
                        UpdateTabOrder(objTab, false);

                        //Update the tab order of all child languages
                        foreach (TabInfo localizedtab in objTab.LocalizedTabs.Values)
                        {
                            if (localizedtab.TabOrder != tabOrder)
                            {
                                localizedtab.TabOrder = tabOrder;
                                UpdateTabOrder(localizedtab, false);
                            }
                        }
                    }

                    tabOrder += increment;
                }

            }
        }

        /// <summary>
        /// Updates the VersionGuid
        /// </summary>
        /// <param name="tabId"></param>
        /// <remarks></remarks>
        private void UpdateTabVersion(int tabId)
        {
            provider.UpdateTabVersion(tabId, Guid.NewGuid());
        }


        public int AddTab(TabInfo objTab)
        {
            return AddTab(objTab, true);
        }
        public int AddTab(TabInfo objTab, bool includeAllTabsModules)
        {
            int tabID = AddTabInternal(objTab, includeAllTabsModules);
            AddTabToEndOfList(objTab, false);
            ClearCache(objTab.PortalID);
            DataCache.RemoveCache(DataCache.PortalDictionaryCacheKey);
            return tabID;
        }
        public int AddTabAfter(TabInfo objTab, int afterTabId)
        {
            List<TabInfo> siblingTabs = GetSiblingTabs(objTab);

            int tabID = AddTabInternal(objTab, true);
            TabInfo afterTab = siblingTabs.Find(t => t.TabID == afterTabId);
            if (afterTab == null)
            {
                //AfterTabId probably relates to a Tab in the current culture (objTab is in a different culture)
                afterTab = GetTab(afterTabId, objTab.PortalID, false);
            }
            objTab.Level = afterTab.Level;
            objTab.TabOrder = afterTab.TabOrder + 1; // tabs will be 1,3(afterTabId),4(newTab),5;

            siblingTabs.Add(objTab);

            //Sort and Update siblings
            UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
            ClearCache(objTab.PortalID);
            return tabID;
        }

        /*public void MoveTabAfter(TabInfo objTab, int afterTabId)
        {
            if ((objTab.TabID < 0))
            {
                return;
            }

            //Get the List of tabs with the same parent
            List<TabInfo> siblingTabs = GetTabsByPortal(objTab.PortalID).WithParentId(objTab.ParentId);
            int siblingCount = siblingTabs.Count;

            //First make sure that the siblings are sorted correctly
            UpdateTabOrder(siblingTabs, 2);

            //New tab is to be inserted into the siblings List after TabId=afterTabId
            for (int index = 0; index <= siblingCount - 1; index++)
            {
                TabInfo sibling = siblingTabs[index];
                if (sibling.TabID == afterTabId)
                {
                    //we need to insert the tab here
                    objTab.Level = sibling.Level;
                    objTab.TabOrder = sibling.TabOrder + 2;

                    //UpdateOrder - Parent hasn't changed so we don't need to regenerate TabPath
                    UpdateTabOrder(objTab, false);

                    //We need to update the taborder for the remaining items, excluding the current tab
                    //UpdateTabOrder(siblingTabs, index + 1, siblingCount - 1, 2)
                    int remainingTabOrder = objTab.TabOrder;
                    for (int remainingIndex = index + 1; remainingIndex <= siblingCount - 1; remainingIndex++)
                    {
                        TabInfo remainingTab = siblingTabs[remainingIndex];

                        if ((remainingTab.TabID == objTab.TabID))
                        {
                            continue;
                        }
                        remainingTabOrder = remainingTabOrder + 2;
                        remainingTab.TabOrder = remainingTabOrder;

                        //UpdateOrder - Parent hasn't changed so we don't need to regenerate TabPath
                        UpdateTabOrder(remainingTab, false);
                    }
                    break; // TODO: might not be correct. Was : Exit For
                }
            }

            //Clear the Cache
            ClearCache(objTab.PortalID);
        }

        public void MoveTabBefore(TabInfo objTab, int beforeTabId)
        {
            if ((objTab.TabID < 0))
            {
                return;
            }

            //Get the List of tabs with the same parent
            List<TabInfo> siblingTabs = GetTabsByPortal(objTab.PortalID).WithParentId(objTab.ParentId);
            int siblingCount = siblingTabs.Count;

            //First make sure that the siblings are sorted correctly
            UpdateTabOrder(siblingTabs, 2);

            //New tab is to be inserted into the siblings List before TabId=beforeTabId
            for (int index = 0; index <= siblingCount - 1; index++)
            {
                TabInfo sibling = siblingTabs[index];
                if (sibling.TabID == beforeTabId)
                {
                    //we need to insert the tab here
                    objTab.Level = sibling.Level;
                    objTab.TabOrder = sibling.TabOrder;

                    //UpdateOrder - Parent hasn't changed so we don't need to regenerate TabPath
                    UpdateTabOrder(objTab, false);

                    //We need to update the taborder for the remaining items, including the current one
                    int remainingTabOrder = objTab.TabOrder;
                    for (int remainingIndex = index; remainingIndex <= siblingCount - 1; remainingIndex++)
                    {
                        TabInfo remainingTab = siblingTabs[remainingIndex];

                        if ((remainingTab.TabID == objTab.TabID))
                        {
                            continue;
                        }

                        remainingTabOrder = remainingTabOrder + 2;
                        remainingTab.TabOrder = remainingTabOrder;

                        //UpdateOrder - Parent hasn't changed so we don't need to regenerate TabPath
                        UpdateTabOrder(remainingTab, false);
                    }
                    break; // TODO: might not be correct. Was : Exit For
                }
            }

            //Clear the Cache
            ClearCache(objTab.PortalID);
        }
         * */

        public int AddTabBefore(TabInfo objTab, int beforeTabId)
        {
            //Get the List of tabs with the same parent
            List<TabInfo> siblingTabs = GetSiblingTabs(objTab);

            //Add tab to store
            int tabID = AddTabInternal(objTab, true);

            //New tab is to be inserted into the siblings List before TabId=beforeTabId
            TabInfo beforeTab = siblingTabs.Find(t => t.TabID == beforeTabId);
            if (beforeTab == null)
            {
                //beforeTabId probably relates to a Tab in the current culture (objTab is in a different culture)
                beforeTab = GetTab(beforeTabId, objTab.PortalID, false);
            }
            objTab.Level = beforeTab.Level;
            objTab.TabOrder = beforeTab.TabOrder - 1; //tabs will be 1,3,4(newTab),5(beforeTabid)
            siblingTabs.Add(objTab);

            //Sort and Update siblings
            UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);

            //Clear the Cache
            ClearCache(objTab.PortalID);

            return tabID;
        }
        public void ClearCache(int portalId)
        {
            DataCache.ClearTabsCache(portalId);
            DataCache.ClearPortalCache(portalId, false);
        }

        /*
        public void CopyTab(int PortalId, int FromTabId, int ToTabId, bool asReference)
        {
            ModuleController objModules = new ModuleController();
            ModuleInfo objModule;
            foreach (KeyValuePair<int, ModuleInfo> kvp in objModules.GetTabModules(FromTabId))
            {
                objModule = kvp.Value;
                if (!objModule.AllTabs)
                {
                    if (asReference == false)
                    {
                        objModule.ModuleID = Null.NullInteger;
                    }
                    objModule.TabID = ToTabId;
                    objModules.AddModule(objModule);
                }
            }
        }
         * */

        public void CreateContentItem(TabInfo updatedTab)
        {
            IContentTypeController typeController = new ContentTypeController();
            ContentType contentType = (from t in typeController.GetContentTypes()
                                       where t.Type == "Tab"
                                       select t).SingleOrDefault();

            //This tab does not have a valid ContentItem
            //create ContentItem
            IContentController contentController = DotNetNuke.Entities.Content.Common.Util.GetContentController();
            if (string.IsNullOrEmpty(updatedTab.Title))
            {
                updatedTab.Content = updatedTab.TabName;
            }
            else
            {
                updatedTab.Content = updatedTab.Title;
            }
            updatedTab.ContentTypeId = contentType.ContentTypeId;
            updatedTab.Indexed = false;
            updatedTab.ContentItemId = contentController.AddContentItem(updatedTab);
        }
        public void DeleteTab(int TabId, int PortalId)
        {
            if (GetTabsByPortal(PortalId).WithParentId(TabId).Count == 0)
            {
                DeleteTabInternal(TabId, PortalId);
                ClearCache(PortalId);
                DataCache.RemoveCache(DataCache.PortalDictionaryCacheKey);
            }
        }
        public void DeleteTab(int TabId, int PortalId, bool deleteDescendants)
        {
            List<TabInfo> descendantList = GetTabsByPortal(PortalId).DescendentsOf(TabId);
            if (deleteDescendants && descendantList.Count > 0)
            {
                for (int i = descendantList.Count - 1; i >= 0; i += -1)
                {
                    DeleteTabInternal(descendantList[i].TabID, PortalId);
                }
                ClearCache(PortalId);
            }
            DeleteTab(TabId, PortalId);
        }
        public ArrayList GetAllTabs(bool CheckLegacyFields)
        {
            return CBO.FillCollection(provider.GetAllTabs(), typeof(TabInfo));
        }
        public ArrayList GetAllTabs()
        {
            return GetAllTabs(true);
        }
        public TabInfo GetTab(int TabId, int PortalId, bool ignoreCache)
        {
            TabInfo tab = null;
            if (!ignoreCache)
            {
                PortalId = GetPortalId(TabId, PortalId);

                //if we have the PortalId then try to get the TabInfo object
                tab = GetTabsByPortal(PortalId).WithTabId(TabId);
            }
            if (ignoreCache || tab == null)
            {
                tab = CBO.FillObject<TabInfo>(provider.GetTab(TabId));
            }
            return tab;
        }

        public TabInfo GetTabByUniqueID(Guid UniqueID)
        {
            TabInfo tab = null;
            tab = CBO.FillObject<TabInfo>(provider.GetTabByUniqueID(UniqueID));
            return tab;
        }

        public TabInfo GetTabByCulture(int tabId, int portalId, Locale locale)
        {
            TabInfo originalTab = null;
            TabInfo localizedTab = null;
            TabCollection tabs = GetTabsByPortal(portalId);

            //Get Tab specified by Id
            originalTab = tabs.WithTabId(tabId);

            if (locale != null && originalTab != null)
            {
                //Check if tab is in the requested culture
                if (string.IsNullOrEmpty(originalTab.CultureCode) || originalTab.CultureCode == locale.Code)
                {
                    localizedTab = originalTab;
                }
                else
                {
                    //See if tab exists for culture
                    if (originalTab.IsDefaultLanguage)
                    {
                        originalTab.LocalizedTabs.TryGetValue(locale.Code, out localizedTab);
                    }
                    else
                    {
                        if (originalTab.DefaultLanguageTab != null)
                        {
                            if (originalTab.DefaultLanguageTab.CultureCode == locale.Code)
                            {
                                localizedTab = originalTab.DefaultLanguageTab;
                            }
                            else
                            {
                                if (!originalTab.DefaultLanguageTab.LocalizedTabs.TryGetValue(locale.Code, out localizedTab))
                                {
                                    localizedTab = originalTab.DefaultLanguageTab;
                                }
                            }
                        }
                    }
                }
            }
            return localizedTab;
        }


        public TabInfo GetTabByName(string TabName, int PortalId)
        {
            return GetTabsByPortal(PortalId).WithTabName(TabName);
        }
        public TabInfo GetTabByName(string TabName, int PortalId, int ParentId)
        {
            return GetTabsByPortal(PortalId).WithTabNameAndParentId(TabName, ParentId);
        }
        public int GetTabCount(int portalId)
        {
            return GetTabsByPortal(portalId).Count;
        }
        public TabCollection GetTabsByPortal(int portalId)
        {
            string cacheKey = string.Format(DataCache.TabCacheKey, portalId.ToString());
            return CBO.GetCachedObject<TabCollection>(new CacheItemArgs(cacheKey, DataCache.TabCacheTimeOut, DataCache.TabCachePriority, portalId), GetTabsByPortalCallBack);
        }
        public IDictionary<int, TabInfo> GetTabsByModuleID(int moduleID)
        {
            return CBO.FillDictionary<int, TabInfo>("TabID", provider.GetTabsByModuleID(moduleID));
        }
        public IDictionary<int, TabInfo> GetTabsByPackageID(int portalID, int packageID, bool forHost)
        {
            return CBO.FillDictionary<int, TabInfo>("TabID", provider.GetTabsByPackageID(portalID, packageID, forHost));
        }
        public void MoveTab(TabInfo objTab, TabMoveType type)
        {
            List<TabInfo> siblingTabs = GetSiblingTabs(objTab);
            int siblingCount = siblingTabs.Count;
            switch (type)
            {
                case TabMoveType.Top:
                    objTab.TabOrder = 1;
                    UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
                    break;
                case TabMoveType.Bottom:
                    objTab.TabOrder = siblingCount * 2 - 1;
                    //Sort and Update siblings
                    UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
                    break;
                case TabMoveType.Up:
                    objTab.TabOrder -= 3;

                    //Sort and Update siblings
                    UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
                    break;
                case TabMoveType.Down:
                    objTab.TabOrder += 3;

                    //Sort and Update siblings
                    UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);
                    break;
                case TabMoveType.Promote:
                    PromoteTab(objTab, siblingTabs);
                    break;
                case TabMoveType.Demote:
                    DemoteTab(objTab, siblingTabs);
                    break;
            }
            ClearCache(objTab.PortalID);
        }

        public void MoveTabAfter(TabInfo objTab, int afterTabId)
        {
            if ((objTab.TabID < 0))
            {
                return;
            }

            //Get the List of tabs with the same parent
            List<TabInfo> siblingTabs = GetSiblingTabs(objTab);

            //tab is to be moved after TabId=afterTabId
            TabInfo afterTab = siblingTabs.Find(t => t.TabID == afterTabId);
            objTab.Level = afterTab.Level;
            objTab.TabOrder = afterTab.TabOrder + 1;
            // tabs will be 1,3(afterTabId),4(moveTab),5

            if(siblingTabs.Find(t => t.TabID == objTab.TabID) != null)
            {
                siblingTabs.Remove(siblingTabs.Find(t => t.TabID == objTab.TabID));
            }

            siblingTabs.Add(objTab);

            //Sort and Update siblings
            UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);

            //Clear the Cache
            ClearCache(objTab.PortalID);
        }

        public void MoveTabBefore(TabInfo objTab, int beforeTabId)
        {
            if ((objTab.TabID < 0))
            {
                return;
            }

            //Get the List of tabs with the same parent
            List<TabInfo> siblingTabs = GetSiblingTabs(objTab);

            //tab is to be moved after TabId=afterTabId
            TabInfo beforeTab = siblingTabs.Find(t => t.TabID == beforeTabId);
            objTab.Level = beforeTab.Level;
            objTab.TabOrder = beforeTab.TabOrder - 1;
            // tabs will be 1,3(afterTabId),4(moveTab),5

            if (siblingTabs.Find(t => t.TabID == objTab.TabID) != null)
            {
                siblingTabs.Remove(siblingTabs.Find(t => t.TabID == objTab.TabID));
            }

            siblingTabs.Add(objTab);

            //Sort and Update siblings
            UpdateTabOrder(siblingTabs, objTab.CultureCode, objTab.PortalID, 2);

            //Clear the Cache
            ClearCache(objTab.PortalID);
        }

        public void PopulateBreadCrumbs(ref TabInfo tab)
        {
            if ((tab.BreadCrumbs == null))
            {
                ArrayList crumbs = new ArrayList();
                PopulateBreadCrumbs(tab.PortalID, ref crumbs, tab.TabID);
                tab.BreadCrumbs = crumbs;
            }
        }
        public void PopulateBreadCrumbs(int portalID, ref ArrayList breadCrumbs, int tabID)
        {
            TabInfo objTab = null;
            TabController objTabController = new TabController();
            TabCollection portalTabs = objTabController.GetTabsByPortal(portalID);
            TabCollection hostTabs = objTabController.GetTabsByPortal(Null.NullInteger);
            bool blnFound = portalTabs.TryGetValue(tabID, out objTab);
            if (!blnFound)
            {
                blnFound = hostTabs.TryGetValue(tabID, out objTab);
            }
            if (blnFound)
            {
                breadCrumbs.Insert(0, objTab.Clone());
                if (!Null.IsNull(objTab.ParentId))
                {
                    PopulateBreadCrumbs(portalID, ref breadCrumbs, objTab.ParentId);
                }
            }
        }

        public void UpdateTab(TabInfo updatedTab)
        {
            TabInfo originalTab = GetTab(updatedTab.TabID, updatedTab.PortalID, true);
            bool updateOrder = (originalTab.ParentId != updatedTab.ParentId);
            int levelDelta = (updatedTab.Level - originalTab.Level);
            bool updateChildren = (originalTab.TabName != updatedTab.TabName || updateOrder);

            //Update ContentItem If neccessary
            if (updatedTab.ContentItemId == Null.NullInteger && updatedTab.TabID != Null.NullInteger)
            {
                CreateContentItem(updatedTab);
            }

            //Update Tab to DataStore
            provider.UpdateTab(updatedTab.TabID, updatedTab.ContentItemId, updatedTab.PortalID, updatedTab.VersionGuid, updatedTab.DefaultLanguageGuid, updatedTab.LocalizedVersionGuid, updatedTab.TabName, updatedTab.IsVisible, updatedTab.DisableLink, updatedTab.ParentId,
            updatedTab.IconFile, updatedTab.IconFileLarge, updatedTab.Title, updatedTab.Description, updatedTab.KeyWords, updatedTab.IsDeleted, updatedTab.Url, updatedTab.SkinSrc, updatedTab.ContainerSrc, updatedTab.TabPath,
            updatedTab.StartDate, updatedTab.EndDate, updatedTab.RefreshInterval, updatedTab.PageHeadText, updatedTab.IsSecure, updatedTab.PermanentRedirect, updatedTab.SiteMapPriority, UserController.GetCurrentUserInfo().UserID, updatedTab.CultureCode);

            //Update Tags
            ITermController termController = DotNetNuke.Entities.Content.Common.Util.GetTermController();
            termController.RemoveTermsFromContent(updatedTab);
            foreach (Term _Term in updatedTab.Terms)
            {
                termController.AddTermToContent(_Term, updatedTab);
            }

            Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
            objEventLog.AddLog(updatedTab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", Services.Log.EventLog.EventLogController.EventLogType.TAB_UPDATED);

            //Update Tab permissions
            TabPermissionController.SaveTabPermissions(updatedTab);

            //Update TabSettings - use Try/catch as tabs are added during upgrade ptocess and the sproc may not exist
            try
            {
                UpdateTabSettings(ref updatedTab);
            }
            catch (Exception ex)
            {
                Exceptions.LogException(ex);
            }

            //Updated Tab Level
            if (levelDelta != 0)
            {
                //Get the descendents
                List<TabInfo> descendantTabs = GetTabsByPortal(updatedTab.PortalID).DescendentsOf(updatedTab.TabID, originalTab.Level);

                //Update the Descendents of this tab
                UpdateDescendantLevel(descendantTabs, levelDelta);
            }

            //Update Tab Order
            if (updateOrder)
            {
                //Tab is being moved from the original list of siblings, so update the Taborder for the remaining tabs
                RemoveTab(originalTab);

                //UpdateOrder - Parent has changed so we need to regenerate TabPath
                AddTabToEndOfList(updatedTab, true);
            }

            //Update Tab Path for descendents
            if (updateChildren)
            {
                //Clear Tab Cache to ensure that previous updates are picked up
                ClearCache(updatedTab.PortalID);
                UpdateChildTabPath(updatedTab.TabID, updatedTab.PortalID);
            }

            //Update Tab Version
            UpdateTabVersion(updatedTab.TabID);

            //Clear Tab Caches
            ClearCache(updatedTab.PortalID);
            if (updatedTab.PortalID != originalTab.PortalID)
            {
                ClearCache(originalTab.PortalID);
            }
        }

        private void UpdateTabSettings(ref TabInfo updatedTab)
        {
            string sKey = null;
            foreach (string sKey_loopVariable in updatedTab.TabSettings.Keys)
            {
                sKey = sKey_loopVariable;
                UpdateTabSetting(updatedTab.TabID, sKey, Convert.ToString(updatedTab.TabSettings[sKey]));
            }
        }

        public void UpdateTabOrder(TabInfo objTab)
        {
            UpdateTabOrder(objTab, true);
        }

        public void UpdateTranslationStatus(TabInfo localizedTab, bool isTranslated)
        {
            if (isTranslated && (localizedTab.DefaultLanguageTab != null))
            {
                localizedTab.LocalizedVersionGuid = localizedTab.DefaultLanguageTab.LocalizedVersionGuid;
            }
            else
            {
                localizedTab.LocalizedVersionGuid = Guid.NewGuid();
            }
            DataProvider.Instance().UpdateTabTranslationStatus(localizedTab.TabID, localizedTab.LocalizedVersionGuid, UserController.GetCurrentUserInfo().UserID);

            //Clear Tab Caches
            ClearCache(localizedTab.PortalID);
        }


        public Hashtable GetTabSettings(int TabId)
        {
            Hashtable objSettings;
            string strCacheKey = "GetTabSettings" + TabId.ToString();
            objSettings = (Hashtable)DataCache.GetCache(strCacheKey);
            if (objSettings == null)
            {
                objSettings = new Hashtable();
                IDataReader dr = provider.GetTabSettings(TabId);
                while (dr.Read())
                {
                    if (!dr.IsDBNull(1))
                    {
                        objSettings[dr.GetString(0)] = dr.GetString(1);
                    }
                    else
                    {
                        objSettings[dr.GetString(0)] = "";
                    }
                }
                dr.Close();
                int intCacheTimeout = 20 * Convert.ToInt32(Host.Host.PerformanceSetting);
                DataCache.SetCache(strCacheKey, objSettings, TimeSpan.FromMinutes(intCacheTimeout));
            }
            return objSettings;
        }
        public void UpdateTabSetting(int TabId, string SettingName, string SettingValue)
        {
            Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
            Services.Log.EventLog.LogInfo objEventLogInfo = new Services.Log.EventLog.LogInfo();
            objEventLogInfo.LogProperties.Add(new DotNetNuke.Services.Log.EventLog.LogDetailInfo("TabId", TabId.ToString()));
            objEventLogInfo.LogProperties.Add(new DotNetNuke.Services.Log.EventLog.LogDetailInfo("SettingName", SettingName.ToString()));
            objEventLogInfo.LogProperties.Add(new DotNetNuke.Services.Log.EventLog.LogDetailInfo("SettingValue", SettingValue.ToString()));
            IDataReader dr = provider.GetTabSetting(TabId, SettingName);
            if (dr.Read())
            {
                provider.UpdateTabSetting(TabId, SettingName, SettingValue, UserController.GetCurrentUserInfo().UserID);
                objEventLogInfo.LogTypeKey = DotNetNuke.Services.Log.EventLog.EventLogController.EventLogType.TAB_SETTING_UPDATED.ToString();
                objEventLog.AddLog(objEventLogInfo);
            }
            else
            {
                provider.AddTabSetting(TabId, SettingName, SettingValue, UserController.GetCurrentUserInfo().UserID);
                objEventLogInfo.LogTypeKey = DotNetNuke.Services.Log.EventLog.EventLogController.EventLogType.TAB_SETTING_CREATED.ToString();
                objEventLog.AddLog(objEventLogInfo);
            }
            dr.Close();

            UpdateTabVersion(TabId);
            DataCache.RemoveCache("GetTabSettings" + TabId.ToString());
        }
        public void DeleteTabSetting(int TabId, string SettingName)
        {
            provider.DeleteTabSetting(TabId, SettingName);
            Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
            Services.Log.EventLog.LogInfo objEventLogInfo = new Services.Log.EventLog.LogInfo();
            objEventLogInfo.LogProperties.Add(new DotNetNuke.Services.Log.EventLog.LogDetailInfo("TabID", TabId.ToString()));
            objEventLogInfo.LogProperties.Add(new DotNetNuke.Services.Log.EventLog.LogDetailInfo("SettingName", SettingName.ToString()));
            objEventLogInfo.LogTypeKey = DotNetNuke.Services.Log.EventLog.EventLogController.EventLogType.TAB_SETTING_DELETED.ToString();
            objEventLog.AddLog(objEventLogInfo);

            UpdateTabVersion(TabId);
            DataCache.RemoveCache("GetTabSettings" + TabId.ToString());
        }
        public void DeleteTabSettings(int TabId)
        {
            provider.DeleteTabSettings(TabId);
            Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
            Services.Log.EventLog.LogInfo objEventLogInfo = new Services.Log.EventLog.LogInfo();
            objEventLogInfo.LogProperties.Add(new DotNetNuke.Services.Log.EventLog.LogDetailInfo("TabId", TabId.ToString()));
            objEventLogInfo.LogTypeKey = DotNetNuke.Services.Log.EventLog.EventLogController.EventLogType.TAB_SETTING_DELETED.ToString();
            objEventLog.AddLog(objEventLogInfo);
            UpdateTabVersion(TabId);
            DataCache.RemoveCache("GetTabSettings" + TabId.ToString());
        }

        #region "Content Localization"

        public void CreateLocalizedCopies(TabInfo originalTab)
        {
            Locale defaultLocale = LocaleController.Instance.GetDefaultLocale(originalTab.PortalID);
            foreach (Locale subLocale in LocaleController.Instance.GetLocales(originalTab.PortalID).Values)
            {
                if (!(subLocale.Code == defaultLocale.Code))
                {
                    CreateLocalizedCopy(originalTab, subLocale);
                }
            }
        }

        public void CreateLocalizedCopy(List<TabInfo> tabs, Locale locale)
        {
            foreach (TabInfo t in tabs)
            {
                CreateLocalizedCopy(t, locale);
            }
        }

        public void CreateLocalizedCopy(TabInfo originalTab, Locale locale)
        {
            //First Clone the Tab
            TabInfo localizedCopy = originalTab.Clone();
            localizedCopy.TabID = Null.NullInteger;

            //Set Guids and Culture Code
            localizedCopy.UniqueId = Guid.NewGuid();
            localizedCopy.VersionGuid = Guid.NewGuid();
            localizedCopy.DefaultLanguageGuid = originalTab.UniqueId;
            localizedCopy.LocalizedVersionGuid = Guid.NewGuid();
            localizedCopy.CultureCode = locale.Code;
            localizedCopy.TabName = localizedCopy.TabName + " (" + locale.Code + ")";

            //Copy Permissions from original Tab for Admins only
            PortalController portalCtrl = new PortalController();
            PortalInfo portal = portalCtrl.GetPortal(originalTab.PortalID);
            localizedCopy.TabPermissions.AddRange(originalTab.TabPermissions.Where(p => p.RoleID == portal.AdministratorRoleId));

            //Get the original Tabs Parent
            TabInfo originalParent = GetTab(originalTab.ParentId, originalTab.PortalID, false);

            if (originalParent != null)
            {
                //Get the localized parent
                TabInfo localizedParent = GetTabByCulture(originalParent.TabID, originalParent.PortalID, locale);

                localizedCopy.ParentId = localizedParent.TabID;
            }

            //Save Tab
            int localizedTabId = AddTabInternal(localizedCopy, true);

            //Update TabOrder for this tab
            UpdateTabOrder(localizedCopy, false);

            //Make shallow copies of all modules
            ModuleController moduleCtrl = new ModuleController();
            moduleCtrl.CopyModules(originalTab, localizedCopy, true);

            //Convert these shallow copies to deep copies
            foreach (KeyValuePair<int, ModuleInfo> kvp in moduleCtrl.GetTabModules(localizedCopy.TabID))
            {
                moduleCtrl.LocalizeModule(kvp.Value, locale);
            }

            //Add Translator Role
            GiveTranslatorRoleEditRights(localizedCopy, null);

            //Clear the Cache
            ClearCache(originalTab.PortalID);
            DataCache.RemoveCache(DataCache.PortalDictionaryCacheKey);

        }

        public List<TabInfo> GetDefaultCultureTabList(int portalid)
        {
            return (from kvp in GetTabsByPortal(portalid)
                    where !kvp.Value.TabPath.StartsWith("//Admin")
                    && !kvp.Value.IsDeleted
                    select kvp.Value).ToList();
        }

        public List<TabInfo> GetCultureTabList(int portalid)
        {
            return (from kvp in GetTabsByPortal(portalid)
                    where !kvp.Value.TabPath.StartsWith("//Admin")
                    && kvp.Value.CultureCode == PortalController.GetCurrentPortalSettings().DefaultLanguage
                    && !kvp.Value.IsDeleted
                    select kvp.Value).ToList();
        }

        public void GiveTranslatorRoleEditRights(TabInfo localizedTab, Dictionary<int, UserInfo> users)
        {
            RoleController roleCtrl = new RoleController();
            PermissionController permissionCtrl = new PermissionController();
            ArrayList permissionsList = permissionCtrl.GetPermissionByCodeAndKey("SYSTEM_TAB", "EDIT");

            string translatorRoles = PortalController.GetPortalSetting(string.Format("DefaultTranslatorRoles-{0}", localizedTab.CultureCode), localizedTab.PortalID, "");
            foreach (string translatorRole in translatorRoles.Split(';'))
            {
                if (users != null)
                {
                    foreach (UserInfo translator in roleCtrl.GetUsersByRoleName(localizedTab.PortalID, translatorRole))
                    {
                        users[translator.UserID] = translator;
                    }
                }

                if (permissionsList != null && permissionsList.Count > 0)
                {
                    PermissionInfo translatePermisison = (PermissionInfo)permissionsList[0];
                    string roleName = translatorRole;
                    RoleInfo role = new RoleController().GetRoleByName(localizedTab.PortalID, roleName);
                    if (role != null)
                    {
                        TabPermissionInfo perm = localizedTab.TabPermissions.Where(tp => tp.RoleID == role.RoleID && tp.PermissionKey == "EDIT").SingleOrDefault();
                        if (perm == null)
                        {
                            //Create Permission
                            TabPermissionInfo tabTranslatePermission = new TabPermissionInfo(translatePermisison);
                            tabTranslatePermission.RoleID = role.RoleID;
                            tabTranslatePermission.AllowAccess = true;
                            tabTranslatePermission.RoleName = roleName;
                            localizedTab.TabPermissions.Add(tabTranslatePermission);
                            UpdateTab(localizedTab);
                        }
                    }
                }

            }
        }

        public void LocalizeTab(TabInfo originalTab, Locale locale)
        {
            originalTab.CultureCode = locale.Code;

            UpdateTab(originalTab);

            //Update culture of modules on this page
            ModuleController moduleCtl = new ModuleController();
            foreach (KeyValuePair<int, ModuleInfo> kvp in moduleCtl.GetTabModules(originalTab.TabID))
            {
                kvp.Value.CultureCode = locale.Code;
                moduleCtl.UpdateModule(kvp.Value);
            }
        }

        public void PublishTab(TabInfo publishTab)
        {
            //To publish a subsidiary language tab we need to enable the View Permissions
            if (publishTab != null && publishTab.DefaultLanguageTab != null)
            {
                foreach (TabPermissionInfo perm in publishTab.DefaultLanguageTab.TabPermissions.Where(p => p.PermissionKey == "VIEW"))
                {
                    TabPermissionInfo sourcePerm = perm;
                    TabPermissionInfo targetPerm = publishTab.TabPermissions.Where(p => p.PermissionKey == sourcePerm.PermissionKey && p.RoleID == sourcePerm.RoleID && p.UserID == sourcePerm.UserID).SingleOrDefault();

                    if (targetPerm == null)
                    {
                        publishTab.TabPermissions.Add(sourcePerm);
                    }

                    TabPermissionController.SaveTabPermissions(publishTab);
                }
            }
        }

        public void PublishTabs(List<TabInfo> tabs)
        {
            foreach (TabInfo t in tabs)
            {
                if (t.IsTranslated)
                {
                    PublishTab(t);
                }
            }
        }

        #endregion


        private static bool DeleteChildTabs(int intTabid, PortalSettings PortalSettings, int UserId)
        {
            TabController objtabs = new TabController();
            bool bDeleted = true;
            foreach (TabInfo objtab in GetTabsByParent(intTabid, PortalSettings.PortalId))
            {
                bDeleted = DeleteTab(objtab, PortalSettings, UserId);
                if (!bDeleted)
                {
                    break;
                }
            }
            return bDeleted;
        }
        private static bool DeleteTab(TabInfo tabToDelete, PortalSettings PortalSettings, int UserId)
        {
            TabController objtabs = new TabController();
            bool bDeleted = true;
            if (!IsSpecialTab(tabToDelete.TabID, PortalSettings))
            {
                if (DeleteChildTabs(tabToDelete.TabID, PortalSettings, UserId))
                {
                    tabToDelete.IsDeleted = true;
                    objtabs.UpdateTab(tabToDelete);

                    ModuleController moduleCtrl = new ModuleController();
                    foreach (ModuleInfo m in moduleCtrl.GetTabModules(tabToDelete.TabID).Values)
                    {
                        moduleCtrl.DeleteTabModule(m.TabID, m.ModuleID, true);
                    }

                    Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
                    objEventLog.AddLog(tabToDelete, PortalSettings, UserId, "", Services.Log.EventLog.EventLogController.EventLogType.TAB_SENT_TO_RECYCLE_BIN);
                }
                else
                {
                    bDeleted = false;
                }
            }
            else
            {
                bDeleted = false;
            }
            return bDeleted;
        }
        private static void DeserializeTabSettings(XmlNodeList nodeTabSettings, TabInfo objTab)
        {
            string sKey;
            string sValue;
            foreach (XmlNode oTabSettingNode in nodeTabSettings)
            {
                sKey = XmlUtils.GetNodeValue(oTabSettingNode.CreateNavigator(), "settingname");
                sValue = XmlUtils.GetNodeValue(oTabSettingNode.CreateNavigator(), "settingvalue");
                objTab.TabSettings[sKey] = sValue;
            }
        }
        private static void DeserializeTabPermissions(XmlNodeList nodeTabPermissions, TabInfo objTab, bool IsAdminTemplate)
        {
            Security.Permissions.PermissionController objPermissionController = new Security.Permissions.PermissionController();
            Security.Permissions.PermissionInfo objPermission;
            Security.Permissions.TabPermissionInfo objTabPermission;
            RoleController objRoleController = new RoleController();
            RoleInfo objRole;
            int RoleID;
            int PermissionID = 0;
            string PermissionKey;
            string PermissionCode;
            string RoleName;
            bool AllowAccess;
            ArrayList arrPermissions;
            int i;
            foreach (XmlNode xmlTabPermission in nodeTabPermissions)
            {
                PermissionKey = XmlUtils.GetNodeValue(xmlTabPermission.CreateNavigator(), "permissionkey");
                PermissionCode = XmlUtils.GetNodeValue(xmlTabPermission.CreateNavigator(), "permissioncode");
                RoleName = XmlUtils.GetNodeValue(xmlTabPermission.CreateNavigator(), "rolename");
                AllowAccess = XmlUtils.GetNodeValueBoolean(xmlTabPermission, "allowaccess");
                arrPermissions = objPermissionController.GetPermissionByCodeAndKey(PermissionCode, PermissionKey);
                for (i = 0; i <= arrPermissions.Count - 1; i++)
                {
                    objPermission = (Security.Permissions.PermissionInfo)arrPermissions[i];
                    PermissionID = objPermission.PermissionID;
                }
                RoleID = int.MinValue;
                switch (RoleName)
                {
                    case DotNetNuke.Common.Globals.glbRoleAllUsersName:
                        RoleID = Convert.ToInt32(DotNetNuke.Common.Globals.glbRoleAllUsers);
                        break;
                    case Common.Globals.glbRoleUnauthUserName:
                        RoleID = Convert.ToInt32(DotNetNuke.Common.Globals.glbRoleUnauthUser);
                        break;
                    default:
                        PortalController objPortals = new PortalController();
                        PortalInfo objPortal = objPortals.GetPortal(objTab.PortalID);
                        objRole = objRoleController.GetRoleByName(objPortal.PortalID, RoleName);
                        if (objRole != null)
                        {
                            RoleID = objRole.RoleID;
                        }
                        else
                        {
                            if (IsAdminTemplate && RoleName.ToLower() == "administrators")
                            {
                                RoleID = objPortal.AdministratorRoleId;
                            }
                        }
                        break;
                }
                if (RoleID != int.MinValue)
                {
                    objTabPermission = new Security.Permissions.TabPermissionInfo();
                    objTabPermission.TabID = objTab.TabID;
                    objTabPermission.PermissionID = PermissionID;
                    objTabPermission.RoleID = RoleID;
                    objTabPermission.AllowAccess = AllowAccess;
                    objTab.TabPermissions.Add(objTabPermission);
                }
            }
        }

        private static int GetPortalId(int TabId, int PortalId)
        {
            if (Null.IsNull(PortalId))
            {
                Dictionary<int, int> portalDic = PortalController.GetPortalDictionary();
                if (portalDic != null && portalDic.ContainsKey(TabId))
                {
                    PortalId = portalDic[TabId];
                }
            }
            return PortalId;
        }


        private static object GetTabsByPortalCallBack(CacheItemArgs cacheItemArgs)
        {
            int portalID = (int)cacheItemArgs.ParamList[0];
            List<TabInfo> tabs = CBO.FillCollection<TabInfo>(provider.GetTabs(portalID));
            return new TabCollection(tabs);
        }
        private static object GetTabPathDictionaryCallback(CacheItemArgs cacheItemArgs)
        {
            string cultureCode = Convert.ToString(cacheItemArgs.ParamList[0]);
            int portalID = (int)cacheItemArgs.ParamList[1];
            Dictionary<string, int> tabpathDic = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
            IDataReader dr = DataProvider.Instance().GetTabPaths(portalID, cultureCode);
            try
            {
                while (dr.Read())
                {
                    tabpathDic[Null.SetNullString(dr["TabPath"])] = Null.SetNullInteger(dr["TabID"]);
                }
            }
            catch (Exception exc)
            {
                DotNetNuke.Services.Exceptions.Exceptions.LogException(exc);
            }
            finally
            {
                CBO.CloseDataReader(dr, true);
            }
            return tabpathDic;
        }
        public static void CopyDesignToChildren(TabInfo parentTab, string skinSrc, string containerSrc)
        {
            CopyDesignToChildren(parentTab, skinSrc, containerSrc, PortalController.GetActivePortalLanguage(parentTab.PortalID));
        }
        public static void CopyDesignToChildren(TabInfo parentTab, string skinSrc, string containerSrc, string CultureCode)
        {
            bool clearCache = Null.NullBoolean;
            List<TabInfo> childTabs = new TabController().GetTabsByPortal(parentTab.PortalID).DescendentsOf(parentTab.TabID);
            TabController objTabController = new TabController();
            foreach (TabInfo objTab in childTabs)
            {
                if (TabPermissionController.CanAdminPage(objTab))
                {
                    provider.UpdateTab(objTab.TabID, objTab.ContentItemId, objTab.PortalID,
                                       objTab.VersionGuid, objTab.DefaultLanguageGuid, objTab.LocalizedVersionGuid,
                                       objTab.TabName, objTab.IsVisible, objTab.DisableLink,
                                       objTab.ParentId, objTab.IconFile, objTab.IconFileLarge, objTab.Title, objTab.Description,
                                       objTab.KeyWords,
                                       objTab.IsDeleted, objTab.Url, skinSrc, containerSrc, objTab.TabPath, objTab.StartDate,
                                       objTab.EndDate, objTab.RefreshInterval, objTab.PageHeadText, objTab.IsSecure,
                                       objTab.PermanentRedirect,
                                       objTab.SiteMapPriority, UserController.GetCurrentUserInfo().UserID, objTab.CultureCode);

                    objTabController.UpdateTabVersion(objTab.TabID);

                    Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
                    objEventLog.AddLog(objTab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", Services.Log.EventLog.EventLogController.EventLogType.TAB_UPDATED);
                    clearCache = true;
                }
            }
            if (clearCache)
            {
                DotNetNuke.Common.Utilities.DataCache.ClearTabsCache(childTabs[0].PortalID);
            }
        }
        public static void CopyPermissionsToChildren(TabInfo parentTab, DotNetNuke.Security.Permissions.TabPermissionCollection newPermissions)
        {
            Security.Permissions.TabPermissionController objTabPermissionController = new Security.Permissions.TabPermissionController();
            bool clearCache = Null.NullBoolean;
            TabController objTabController = new TabController();
            List<TabInfo> childTabs = new TabController().GetTabsByPortal(parentTab.PortalID).DescendentsOf(parentTab.TabID);
            foreach (TabInfo objTab in childTabs)
            {
                if (TabPermissionController.CanAdminPage(objTab))
                {
                    objTab.TabPermissions.Clear();
                    objTab.TabPermissions.AddRange(newPermissions);
                    TabPermissionController.SaveTabPermissions(objTab);
                    objTabController.UpdateTabVersion(objTab.TabID);
                    clearCache = true;
                }
            }
            if (clearCache)
            {
                DotNetNuke.Common.Utilities.DataCache.ClearTabsCache(childTabs[0].PortalID);
            }
        }
        public static bool DeleteTab(int tabId, PortalSettings PortalSettings, int UserId)
        {
            bool bDeleted = true;
            TabController objController = new TabController();
            TabInfo objTab = objController.GetTab(tabId, PortalSettings.PortalId, false);
            if (objTab != null)
            {
                if (objTab.DefaultLanguageTab != null)
                {
                    //We are trying to delete the child, so recall this function with the master language's tab id
                    return DeleteTab(objTab.DefaultLanguageTab.TabID, PortalSettings, UserId);
                }
                //Delete Tab
                bDeleted = DeleteTab(objTab, PortalSettings, UserId);

                //Delete any localized children
                if (bDeleted)
                {
                    foreach (TabInfo localizedtab in objTab.LocalizedTabs.Values)
                    {
                        DeleteTab(localizedtab, PortalSettings, UserId);
                    }
                }

                //Get the List of tabs with the same parent
                List<TabInfo> siblingTabs = objController.GetSiblingTabs(objTab);

                //Update TabOrder
                objController.UpdateTabOrder(siblingTabs, objTab.CultureCode, PortalSettings.PortalId, 2);

            }
            else
            {
                bDeleted = false;
            }
            return bDeleted;
        }
        public static void DeserializePanes(XmlNode nodePanes, int PortalId, int TabId, PortalTemplateModuleAction mergeTabs, Hashtable hModules)
        {
            ModuleController objModules = new ModuleController();
            ModuleInfo objModule;
            Dictionary<int, ModuleInfo> dicModules = objModules.GetTabModules(TabId);
            if (mergeTabs == PortalTemplateModuleAction.Replace)
            {
                foreach (KeyValuePair<int, ModuleInfo> kvp in dicModules)
                {
                    objModule = kvp.Value;
                    objModules.DeleteTabModule(TabId, objModule.ModuleID, false);
                }
            }
            foreach (XmlNode nodePane in nodePanes.ChildNodes)
            {
                if (nodePane.SelectSingleNode("modules") != null)
                {
                    foreach (XmlNode nodeModule in nodePane.SelectSingleNode("modules"))
                    {
                        ModuleController.DeserializeModule(nodeModule, nodePane, PortalId, TabId, mergeTabs, hModules);
                    }
                }
            }
        }
        public static TabInfo DeserializeTab(XmlNode nodeTab, TabInfo objTab, int PortalId, PortalTemplateModuleAction mergeTabs)
        {
            return TabController.DeserializeTab(nodeTab, objTab, new Hashtable(), PortalId, false, mergeTabs, new Hashtable());
        }
        public static TabInfo DeserializeTab(XmlNode nodeTab, TabInfo objTab, Hashtable hTabs, int PortalId, bool IsAdminTemplate, PortalTemplateModuleAction mergeTabs, Hashtable hModules)
        {
            TabController objTabs = new TabController();
            string tabName = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "name");
            if (!String.IsNullOrEmpty(tabName))
            {
                if (objTab == null)
                {
                    objTab = new TabInfo();
                    objTab.TabID = Null.NullInteger;
                    objTab.ParentId = Null.NullInteger;
                    objTab.TabName = tabName;
                }
                objTab.PortalID = PortalId;
                objTab.Title = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "title");
                objTab.Description = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "description");
                objTab.KeyWords = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "keywords");
                objTab.IsVisible = XmlUtils.GetNodeValueBoolean(nodeTab, "visible", true);
                objTab.DisableLink = XmlUtils.GetNodeValueBoolean(nodeTab, "disabled");
                objTab.IconFile = DotNetNuke.Common.Globals.ImportFile(PortalId, XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "iconfile"));
                objTab.IconFileLarge = DotNetNuke.Common.Globals.ImportFile(PortalId, XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "iconfilelarge"));
                objTab.Url = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "url");
                objTab.StartDate = XmlUtils.GetNodeValueDate(nodeTab, "startdate", Null.NullDate);
                objTab.EndDate = XmlUtils.GetNodeValueDate(nodeTab, "enddate", Null.NullDate);
                objTab.RefreshInterval = XmlUtils.GetNodeValueInt(nodeTab, "refreshinterval", Null.NullInteger);
                objTab.PageHeadText = XmlUtils.GetNodeValue(nodeTab, "pageheadtext", Null.NullString);
                objTab.IsSecure = XmlUtils.GetNodeValueBoolean(nodeTab, "issecure", false);
                objTab.SiteMapPriority = XmlUtils.GetNodeValueSingle(nodeTab, "sitemappriority", (float)0.5);
                //objTab.UniqueId = New Guid(XmlUtils.GetNodeValue(nodeTab, "guid", Guid.NewGuid.ToString()));
                //objTab.VersionGuid = New Guid(XmlUtils.GetNodeValue(nodeTab, "versionGuid", Guid.NewGuid.ToString()));
                objTab.TabPermissions.Clear();
                DeserializeTabPermissions(nodeTab.SelectNodes("tabpermissions/permission"), objTab, IsAdminTemplate);
                DeserializeTabSettings(nodeTab.SelectNodes("tabsettings/tabsetting"), objTab);
                if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeTab, "skinsrc", "")))
                {
                    objTab.SkinSrc = XmlUtils.GetNodeValue(nodeTab, "skinsrc", "");
                }
                if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeTab, "containersrc", "")))
                {
                    objTab.ContainerSrc = XmlUtils.GetNodeValue(nodeTab, "containersrc", "");
                }
                tabName = objTab.TabName;
                if (!String.IsNullOrEmpty(XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "parent")))
                {
                    if (hTabs[XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "parent")] != null)
                    {
                        objTab.ParentId = Convert.ToInt32(hTabs[XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "parent")]);
                        tabName = XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "parent") + "/" + objTab.TabName;
                    }
                    else
                    {
                        TabInfo objParent = objTabs.GetTabByName(XmlUtils.GetNodeValue(nodeTab.CreateNavigator(), "parent"), PortalId);
                        if (objParent != null)
                        {
                            objTab.ParentId = objParent.TabID;
                            tabName = objParent.TabName + "/" + objTab.TabName;
                        }
                        else
                        {
                            objTab.ParentId = Null.NullInteger;
                            tabName = objTab.TabName;
                        }
                    }
                }
                if (objTab.TabID == Null.NullInteger)
                {
                    objTab.TabID = objTabs.AddTab(objTab);
                }
                else
                {
                    objTabs.UpdateTab(objTab);
                }
                if (hTabs[tabName] == null)
                {
                    hTabs.Add(tabName, objTab.TabID);
                }
            }
            if (nodeTab.SelectSingleNode("panes") != null)
            {
                DeserializePanes(nodeTab.SelectSingleNode("panes"), PortalId, objTab.TabID, mergeTabs, hModules);
            }
            nodeTab.AppendChild(XmlUtils.CreateElement(nodeTab.OwnerDocument, "tabid", objTab.TabID.ToString()));
            return objTab;
        }
        public static List<TabInfo> GetPortalTabs(int portalId, int excludeTabId, bool includeNoneSpecified, bool includeHidden)
        {
            return GetPortalTabs(GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true), excludeTabId, includeNoneSpecified, "<" + Localization.GetString("None_Specified") + ">", includeHidden, false, false, false, false);
        }
        public static List<TabInfo> GetPortalTabs(int portalId, int excludeTabId, bool includeNoneSpecified, bool includeHidden, bool includeDeleted, bool includeURL)
        {
            return GetPortalTabs(GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true), excludeTabId, includeNoneSpecified, "<" + Localization.GetString("None_Specified") + ">", includeHidden, includeDeleted, includeURL, false, false);
        }
        public static List<TabInfo> GetPortalTabs(int portalId, int excludeTabId, bool includeNoneSpecified, string NoneSpecifiedText, bool includeHidden, bool includeDeleted, bool includeURL, bool checkViewPermisison, bool checkEditPermission)
        {
            return GetPortalTabs(GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true), excludeTabId, includeNoneSpecified, NoneSpecifiedText, includeHidden, includeDeleted, includeURL, checkViewPermisison, checkEditPermission);
        }
        public static List<TabInfo> GetPortalTabs(List<TabInfo> tabs, int excludeTabId, bool includeNoneSpecified, string NoneSpecifiedText, bool includeHidden, bool includeDeleted, bool includeURL, bool checkViewPermisison, bool checkEditPermission)
        {
            List<TabInfo> listTabs = new List<TabInfo>();
            if (includeNoneSpecified)
            {
                TabInfo objTab = new TabInfo();
                objTab.TabID = -1;
                objTab.TabName = NoneSpecifiedText;
                objTab.TabOrder = 0;
                objTab.ParentId = -2;
                listTabs.Add(objTab);
            }
            foreach (TabInfo objTab in tabs)
            {
                UserInfo objUserInfo = UserController.GetCurrentUserInfo();
                if (((excludeTabId < 0) || (objTab.TabID != excludeTabId)) && (!objTab.IsSuperTab || objUserInfo.IsSuperUser))
                {
                    if ((objTab.IsVisible == true || includeHidden == true) && (objTab.IsDeleted == false || includeDeleted == true) && (objTab.TabType == TabType.Normal || includeURL == true))
                    {
                        if (checkEditPermission || checkViewPermisison)
                        {
                            string permissionList = "ADD,COPY,EDIT,MANAGE";
                            if (checkEditPermission && TabPermissionController.HasTabPermission(objTab.TabPermissions, permissionList))
                            {
                                listTabs.Add(objTab);
                            }
                            else if (checkViewPermisison && TabPermissionController.CanViewPage(objTab))
                            {
                                listTabs.Add(objTab);
                            }
                        }
                        else
                        {
                            listTabs.Add(objTab);
                        }
                    }
                }
            }
            return listTabs;
        }
        public static int GetTabByTabPath(int portalId, string tabPath, string cultureCode)
        {
            Dictionary<string, int> tabpathDic = GetTabPathDictionary(portalId, cultureCode);
            if (tabpathDic.ContainsKey(tabPath))
            {
                return tabpathDic[tabPath];
            }
            else
            {
                return -1;
            }
        }
        public static Dictionary<string, int> GetTabPathDictionary(int portalId, string cultureCode)
        {
            string cacheKey = string.Format(DataCache.TabPathCacheKey, cultureCode, portalId.ToString());
            return CBO.GetCachedObject<Dictionary<string, int>>(new CacheItemArgs(cacheKey, DataCache.TabPathCacheTimeOut, DataCache.TabPathCachePriority, cultureCode, portalId), GetTabPathDictionaryCallback);
        }
        public static List<TabInfo> GetTabsByParent(int parentId, int portalId)
        {
            return new TabController().GetTabsByPortal(portalId).WithParentId(parentId);
        }
        public static List<TabInfo> GetTabsBySortOrder(int portalId, string cultureCode, bool includeNeutral)
        {
            return new TabController().GetTabsByPortal(portalId).WithCulture(cultureCode, includeNeutral).AsList();
        }

        public static bool IsSpecialTab(int tabId, PortalSettings PortalSettings)
        {
            return tabId == PortalSettings.SplashTabId || tabId == PortalSettings.HomeTabId || tabId == PortalSettings.LoginTabId || tabId == PortalSettings.UserTabId || tabId == PortalSettings.AdminTabId || tabId == PortalSettings.SuperTabId;
        }
        public static void RestoreTab(TabInfo objTab, PortalSettings PortalSettings, int UserId)
        {
            Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
            TabController objController = new TabController();

            if (objTab.DefaultLanguageTab != null)
            {
                //We are trying to restore the child, so recall this function with the master language's tab id
                RestoreTab(objTab.DefaultLanguageTab, PortalSettings, UserId);
                return;
            }

            objTab.IsDeleted = false;
            objController.UpdateTab(objTab);

            //Restore any localized children
            foreach (TabInfo localizedtab in objTab.LocalizedTabs.Values)
            {
                localizedtab.IsDeleted = false;
                objController.UpdateTab(localizedtab);
            }

            List<TabInfo> siblingTabs = objController.GetSiblingTabs(objTab);

            objController.UpdateTabOrder(siblingTabs, objTab.CultureCode, PortalSettings.PortalId, 2);

            objEventLog.AddLog(objTab, PortalSettings, UserId, "", Services.Log.EventLog.EventLogController.EventLogType.TAB_RESTORED);
            ModuleController objmodules = new ModuleController();
            ArrayList arrMods = objmodules.GetAllTabsModules(objTab.PortalID, true);
            foreach (ModuleInfo objModule in arrMods)
            {
                objmodules.CopyModule(objModule, objTab, Null.NullString, true);
            }
            objController.ClearCache(objTab.PortalID);
        }
        public static XmlNode SerializeTab(XmlDocument xmlTab, TabInfo objTab, bool includeContent)
        {
            return SerializeTab(xmlTab, null, objTab, null, includeContent);
        }
        public static XmlNode SerializeTab(XmlDocument xmlTab, Hashtable hTabs, TabInfo objTab, PortalInfo objPortal, bool includeContent)
        {
            XmlNode nodeTab;
            XmlNode urlNode;
            XmlNode newnode;
            CBO.SerializeObject(objTab, xmlTab);
            nodeTab = xmlTab.SelectSingleNode("tab");
            nodeTab.Attributes.Remove(nodeTab.Attributes["xmlns:xsd"]);
            nodeTab.Attributes.Remove(nodeTab.Attributes["xmlns:xsi"]);
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("tabid"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("moduleID"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("taborder"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("portalid"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("parentid"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("isdeleted"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("tabpath"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("haschildren"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("skindoctype"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("uniqueid"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("versionguid"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("cultureCode"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("defaultLanguageGuid"));
            nodeTab.RemoveChild(nodeTab.SelectSingleNode("localizedVersionGuid"));
            foreach (XmlNode nodePermission in nodeTab.SelectNodes("tabpermissions/permission"))
            {
                nodePermission.RemoveChild(nodePermission.SelectSingleNode("tabpermissionid"));
                nodePermission.RemoveChild(nodePermission.SelectSingleNode("permissionid"));
                nodePermission.RemoveChild(nodePermission.SelectSingleNode("tabid"));
                nodePermission.RemoveChild(nodePermission.SelectSingleNode("roleid"));
                nodePermission.RemoveChild(nodePermission.SelectSingleNode("userid"));
                nodePermission.RemoveChild(nodePermission.SelectSingleNode("username"));
                nodePermission.RemoveChild(nodePermission.SelectSingleNode("displayname"));
            }
            urlNode = xmlTab.SelectSingleNode("tab/url");
            switch (objTab.TabType)
            {
                case TabType.Normal:
                    urlNode.Attributes.Append(XmlUtils.CreateAttribute(xmlTab, "type", "Normal"));
                    break;
                case TabType.Tab:
                    urlNode.Attributes.Append(XmlUtils.CreateAttribute(xmlTab, "type", "Tab"));
                    TabInfo tab = new TabController().GetTab(Int32.Parse(objTab.Url), objTab.PortalID, false);
                    urlNode.InnerXml = tab.TabPath;
                    break;
                case TabType.File:
                    urlNode.Attributes.Append(XmlUtils.CreateAttribute(xmlTab, "type", "File"));
                    Services.FileSystem.FileInfo file = new Services.FileSystem.FileController().GetFileById(Int32.Parse(objTab.Url.Substring(7)), objTab.PortalID);
                    urlNode.InnerXml = file.RelativePath;
                    break;
                case TabType.Url:
                    urlNode.Attributes.Append(XmlUtils.CreateAttribute(xmlTab, "type", "Url"));
                    break;
            }
            XmlUtils.SerializeHashtable(objTab.TabSettings, xmlTab, nodeTab, "tabsetting", "settingname", "settingvalue");
            if (objPortal != null)
            {
                if (objTab.TabID == objPortal.SplashTabId)
                {
                    newnode = xmlTab.CreateElement("tabtype");
                    newnode.InnerXml = "splashtab";
                    nodeTab.AppendChild(newnode);
                }
                else if (objTab.TabID == objPortal.HomeTabId)
                {
                    newnode = xmlTab.CreateElement("tabtype");
                    newnode.InnerXml = "hometab";
                    nodeTab.AppendChild(newnode);
                }
                else if (objTab.TabID == objPortal.UserTabId)
                {
                    newnode = xmlTab.CreateElement("tabtype");
                    newnode.InnerXml = "usertab";
                    nodeTab.AppendChild(newnode);
                }
                else if (objTab.TabID == objPortal.LoginTabId)
                {
                    newnode = xmlTab.CreateElement("tabtype");
                    newnode.InnerXml = "logintab";
                    nodeTab.AppendChild(newnode);
                }
            }
            if (hTabs != null)
            {
                if (!Null.IsNull(objTab.ParentId))
                {
                    newnode = xmlTab.CreateElement("parent");
                    newnode.InnerXml = HttpContext.Current.Server.HtmlEncode(hTabs[objTab.ParentId].ToString());
                    nodeTab.AppendChild(newnode);
                    hTabs.Add(objTab.TabID, hTabs[objTab.ParentId].ToString() + "/" + objTab.TabName);
                }
                else
                {
                    hTabs.Add(objTab.TabID, objTab.TabName);
                }
            }
            XmlNode nodePanes;
            XmlNode nodePane;
            XmlNode nodeName;
            XmlNode nodeModules;
            XmlNode nodeModule;
            XmlDocument xmlModule;
            ModuleInfo objmodule;
            ModuleController objmodules = new ModuleController();
            nodePanes = nodeTab.AppendChild(xmlTab.CreateElement("panes"));
            foreach (KeyValuePair<int, ModuleInfo> kvp in objmodules.GetTabModules(objTab.TabID))
            {
                objmodule = kvp.Value;
                if (!objmodule.IsDeleted)
                {
                    xmlModule = new XmlDocument();
                    nodeModule = ModuleController.SerializeModule(xmlModule, objmodule, includeContent);
                    if (nodePanes.SelectSingleNode("descendant::pane[name='" + objmodule.PaneName + "']") == null)
                    {
                        nodePane = xmlModule.CreateElement("pane");
                        nodeName = nodePane.AppendChild(xmlModule.CreateElement("name"));
                        nodeName.InnerText = objmodule.PaneName;
                        nodePane.AppendChild(xmlModule.CreateElement("modules"));
                        nodePanes.AppendChild(xmlTab.ImportNode(nodePane, true));
                    }
                    nodeModules = nodePanes.SelectSingleNode("descendant::pane[name='" + objmodule.PaneName + "']/modules");
                    nodeModules.AppendChild(xmlTab.ImportNode(nodeModule, true));
                }
            }
            return nodeTab;
        }

        [Obsolete("Deprecated in DotNetNuke 5.5.Replaced by ModuleController.CopyModules")]
        public void CopyTab(int PortalId, int FromTabId, int ToTabId, bool asReference)
        {
            ModuleController objModules = new ModuleController();
            TabInfo sourceTab = GetTab(FromTabId, PortalId, false);
            TabInfo destinationTab = GetTab(FromTabId, ToTabId, false);

            if (sourceTab != null && destinationTab != null)
            {
                objModules.CopyModules(sourceTab, destinationTab, asReference);
            }
        }


        [Obsolete("This method has replaced in DotNetNuke 5.0 by DeserializeTab(ByVal nodeTab As XmlNode, ByVal objTab As TabInfo, ByVal PortalId As Integer, ByVal mergeTabs As PortalTemplateModuleAction)")]
        public static TabInfo DeserializeTab(string tabName, XmlNode nodeTab, int PortalId)
        {
            return TabController.DeserializeTab(nodeTab, null, new Hashtable(), PortalId, false, PortalTemplateModuleAction.Ignore, new Hashtable());
        }
        [Obsolete("This method has replaced in DotNetNuke 5.0 by DeserializeTab(ByVal nodeTab As XmlNode, ByVal objTab As TabInfo, ByVal PortalId As Integer, ByVal mergeTabs As PortalTemplateModuleAction)")]
        public static TabInfo DeserializeTab(XmlNode nodeTab, TabInfo objTab, int PortalId)
        {
            return TabController.DeserializeTab(nodeTab, objTab, new Hashtable(), PortalId, false, PortalTemplateModuleAction.Ignore, new Hashtable());
        }
        [Obsolete("This method has replaced in DotNetNuke 5.0 by DeserializeTab(ByVal nodeTab As XmlNode, ByVal objTab As TabInfo, ByVal hTabs As Hashtable, ByVal PortalId As Integer, ByVal IsAdminTemplate As Boolean, ByVal mergeTabs As PortalTemplateModuleAction, ByVal hModules As Hashtable)")]
        public static TabInfo DeserializeTab(string tabName, XmlNode nodeTab, TabInfo objTab, Hashtable hTabs, int PortalId, bool IsAdminTemplate, PortalTemplateModuleAction mergeTabs, Hashtable hModules)
        {
            return TabController.DeserializeTab(nodeTab, objTab, hTabs, PortalId, IsAdminTemplate, mergeTabs, hModules);
        }
        [Obsolete("This method has replaced in DotNetNuke 5.0 by CopyDesignToChildren(TabInfo,String, String)")]
        public void CopyDesignToChildren(ArrayList tabs, string skinSrc, string containerSrc)
        {
            foreach (TabInfo objTab in tabs)
            {
                provider.UpdateTab(objTab.TabID, objTab.ContentItemId, objTab.PortalID,
                                   objTab.VersionGuid, objTab.DefaultLanguageGuid, objTab.LocalizedVersionGuid,
                                   objTab.TabName, objTab.IsVisible, objTab.DisableLink,
                                   objTab.ParentId, objTab.IconFile, objTab.IconFileLarge, objTab.Title, objTab.Description,
                                   objTab.KeyWords,
                                   objTab.IsDeleted, objTab.Url, skinSrc, containerSrc, objTab.TabPath, objTab.StartDate,
                                   objTab.EndDate, objTab.RefreshInterval, objTab.PageHeadText, objTab.IsSecure,
                                   objTab.PermanentRedirect,
                                   objTab.SiteMapPriority, UserController.GetCurrentUserInfo().UserID, objTab.CultureCode);
                Services.Log.EventLog.EventLogController objEventLog = new Services.Log.EventLog.EventLogController();
                objEventLog.AddLog(objTab, PortalController.GetCurrentPortalSettings(), UserController.GetCurrentUserInfo().UserID, "", Services.Log.EventLog.EventLogController.EventLogType.TAB_UPDATED);
            }
            if (tabs.Count > 0)
            {
                DotNetNuke.Common.Utilities.DataCache.ClearTabsCache(((TabInfo)tabs[0]).PortalID);
            }
        }
        [Obsolete("Deprecated in DotNetNuke 5.0. Replaced by CopyPermissionsToChildren(TabInfo, TabPermissionCollection)")]
        public void CopyPermissionsToChildren(ArrayList tabs, DotNetNuke.Security.Permissions.TabPermissionCollection newPermissions)
        {
            Security.Permissions.TabPermissionController objTabPermissionController = new Security.Permissions.TabPermissionController();
            foreach (TabInfo objTab in tabs)
            {
                objTab.TabPermissions.Clear();
                objTab.TabPermissions.AddRange(newPermissions);
                TabPermissionController.SaveTabPermissions(objTab);
            }
            if (tabs.Count > 0)
            {
                DotNetNuke.Common.Utilities.DataCache.ClearTabsCache(((TabInfo)tabs[0]).PortalID);
            }
        }
        [Obsolete("This method is obsolete.  It has been replaced by GetTab(ByVal TabId As Integer, ByVal PortalId As Integer, ByVal ignoreCache As Boolean) ")]
        public TabInfo GetTab(int TabId)
        {
            return CBO.FillObject<TabInfo>(DataProvider.Instance().GetTab(TabId));
        }

        [Obsolete("Deprecated in DNN 5.5. Replaced by GetTabByTabPath(portalId, tabPath, cultureCode) ")]
        public static int GetTabByTabPath(int portalId, string tabPath)
        {
            return GetTabByTabPath(portalId, tabPath, Null.NullString);
        }

        [Obsolete("Deprecated in DNN 5.5. Replaced by GetTabPathDictionary(portalId, cultureCode) ")]
        public static Dictionary<string, int> GetTabPathDictionary(int portalId)
        {
            return GetTabPathDictionary(portalId, Null.NullString);
        }


        [Obsolete("This method has been replaced in 5.0 by GetTabPathDictionary(ByVal portalId As Integer) As Dictionary(Of String, Integer) ")]
        public static Dictionary<string, int> GetTabPathDictionary()
        {
            Dictionary<string, int> tabpathDic = new Dictionary<string, int>(StringComparer.CurrentCultureIgnoreCase);
            IDataReader dr = DataProvider.Instance().GetTabPaths(Null.NullInteger, Null.NullString);
            try
            {
                while (dr.Read())
                {
                    string strKey = "//" + Null.SetNullInteger(dr["PortalID"]) + Null.SetNullString(dr["TabPath"]);
                    tabpathDic[strKey] = Null.SetNullInteger(dr["TabID"]);
                }
            }
            catch (Exception exc)
            {
                DotNetNuke.Services.Exceptions.Exceptions.LogException(exc);
            }
            finally
            {
                CBO.CloseDataReader(dr, true);
            }
            return tabpathDic;
        }
        [Obsolete("This method has replaced in DotNetNuke 5.0 by GetTabsByPortal()")]
        public ArrayList GetTabs(int PortalId)
        {
            return GetTabsByPortal(PortalId).ToArrayList();
        }
        [Obsolete("This method is obsolete.  It has been replaced by GetTabsByParent(ByVal ParentId As Integer, ByVal PortalId As Integer) ")]
        public ArrayList GetTabsByParentId(int ParentId)
        {
            return CBO.FillCollection((DataProvider.Instance().GetTabsByParentId(ParentId)), typeof(TabInfo));
        }
        [Obsolete("This method has replaced in DotNetNuke 5.0 by GetTabsByParent(ByVal ParentId As Integer, ByVal PortalId As Integer)")]
        public ArrayList GetTabsByParentId(int ParentId, int PortalId)
        {
            ArrayList arrTabs = new ArrayList();
            foreach (TabInfo objTab in GetTabsByParent(ParentId, PortalId))
            {
                arrTabs.Add(objTab);
            }
            return arrTabs;
        }

        [Obsolete("Deprecated in DNN 5.5. Replaced by GetTabsBySortOrder(portalId, cultureCode) ")]
        public static List<TabInfo> GetTabsBySortOrder(int portalId)
        {
            return GetTabsBySortOrder(portalId, PortalController.GetActivePortalLanguage(portalId), true);
        }

        [Obsolete("Deprecated in DNN 5.5. Replaced by UpdateTab(updatedTab)")]
        public void UpdateTab(TabInfo updatedTab, string CultureCode)
        {
            updatedTab.CultureCode = CultureCode;
            UpdateTab(updatedTab);
        }


        [Obsolete("This method is obsolete.  It has been replaced by UpdateTabOrder(ByVal objTab As TabInfo) ")]
        public void UpdateTabOrder(int PortalID, int TabId, int TabOrder, int Level, int ParentId)
        {
            TabInfo objTab = GetTab(TabId, PortalID, false);
            objTab.TabOrder = TabOrder;
            objTab.Level = Level;
            objTab.ParentId = ParentId;
            UpdateTabOrder(objTab);
        }
    }
}
